﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

using ArcannEngine.Scene;
using ArcannEngine.Render;

namespace ArcannEngine
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class RocketGame : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        RenderManager renderManager;
        private Dictionary<String, Manager> managers;

        public Dictionary<String, Manager> Managers
        {
            get { return this.managers; }
        }

        public GraphicsDeviceManager Graphics
        {
            get { return this.graphics; }
            set { this.graphics = value; }
        }

        public RocketGame()
        {
            graphics = new GraphicsDeviceManager(this);
            graphics.PreferredBackBufferWidth = 1280;
            graphics.PreferredBackBufferHeight = 720;
            graphics.PreferMultiSampling = true;
            graphics.IsFullScreen = false;
            this.IsMouseVisible = false;
            Content.RootDirectory = "Content";

            managers = new Dictionary<string, Manager>();
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            SceneManager sceneManager = new SceneManager(this);
            renderManager = new RenderManager(this);

            base.Initialize();
        }

        public void AddManager(Manager manager)
        {
            Manager checkManager = null;
            if (managers.TryGetValue(manager.Name, out checkManager))
            {
                throw new Exception("Manager type " + manager.Name + " already exists within the game engine");
            }
            managers.Add(manager.Name, manager);
        }

        public Manager GetManager(String managerName)
        {
            Manager manager = null;
            if (!managers.TryGetValue(managerName, out manager))
            {
            }

            return manager;
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            foreach (KeyValuePair<String, Manager> pair in managers)
            {
                (pair.Value).LoadContent();
            }
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            foreach (KeyValuePair<String, Manager> pair in managers)
            {
                (pair.Value).UnloadContent();
            }
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            foreach (KeyValuePair<String, Manager> pair in managers)
            {
                (pair.Value).Update(gameTime);
                KeyboardState key = Keyboard.GetState();
                
                if (key.IsKeyDown(Keys.Escape) || GamePad.GetState(PlayerIndex.One).IsButtonDown(Buttons.Back))
                {
                    this.Exit();
                }
            }
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            foreach (KeyValuePair<String, Manager> pair in managers)
            {
                (pair.Value).Draw(gameTime);
            }
            base.Draw(gameTime);
            renderManager.DrawInterfaceTemp();
        }
    }
}
